﻿using System;
using System.Collections.Generic;
using System.Windows.Media.Imaging;

using Holdem.Core.Statistics;
using Holdem.Interfaces;
using Holdem.Interfaces.Card;
using Holdem.Interfaces.Configuration;
using Holdem.Interfaces.HandHistory;
using Holdem.Interfaces.Service;
using Holdem.Interfaces.ViewModel;

using Microsoft.Phone.Reactive;

namespace Holdem.ViewModel
{
    public abstract class HoldemViewModelBase : HoldemViewModelCommandBase, IViewModel
    {
        #region Constants

    	protected const double EPSILON = 0.005;

        #endregion //Constants

        #region Instance Variables

    	private readonly ICardThemeManager _themeManager;
        private readonly IAdProvider _adProvider;

        #endregion //Instance Variables

        #region Public Properties

        public virtual string Title
        {
            get;
            set;
        }

        public virtual int NumberOfPlayers
        {
            get
            {
                return PersistConfig.Cast<int>(ConfigKey.HoldemOptionsViewNumberOfPlayers);
            }
            set
            {
                PersistConfig[ConfigKey.HoldemOptionsViewNumberOfPlayers] = value;

                base.RaisePropertyChanged("NumberOfPlayers");
            }
        }

        public HoldemCard CurrentState
        {
            get;
            set;
        }

        public int CurrentIndex { get; set; }

        protected virtual History Current { get; set; }

        public IEnumerable<BitmapImage> HoldemHandCards
        {
            get
            {
                return
                    new List<BitmapImage>
                    {
                        GetCardImageBasedOnState(HoldemCard.Flop3, HoldemCard.Flop1),
                        GetCardImageBasedOnState(HoldemCard.Flop3, HoldemCard.Flop2),
                        GetCardImageBasedOnState(HoldemCard.Flop3, HoldemCard.Flop3),
                        GetCardImageBasedOnState(HoldemCard.Turn, HoldemCard.Turn),
                        GetCardImageBasedOnState(HoldemCard.River, HoldemCard.River)
                    };
            }
        }

        public IEnumerable<BitmapImage> HoldemHoleCards
        {
            get
            {
                return
                    new List<BitmapImage>
                    {
                        this.GetCardImage(HoldemCard.Hole1),
                        this.GetCardImage(HoldemCard.Hole2)
                    };
            }
        }

        public int Precision
        {
            get
            {
                var precision = PersistConfig.Cast<int>(ConfigKey.HoldemOptionsViewPrecision);

                if (precision > HoldemStatisticsBase.MaxPrecision)
                    PersistConfig[ConfigKey.HoldemOptionsViewPrecision] = (int)HoldemStatisticsBase.MaxPrecision;
                if (precision < HoldemStatisticsBase.MinPrecision)
                    PersistConfig[ConfigKey.HoldemOptionsViewPrecision] = (int)HoldemStatisticsBase.MinPrecision;

                return PersistConfig.Cast<int>(ConfigKey.HoldemOptionsViewPrecision);
            }
            set
            {
                if (value > HoldemStatisticsBase.MaxPrecision)
                    PersistConfig[ConfigKey.HoldemOptionsViewPrecision] = (int)HoldemStatisticsBase.MaxPrecision;
                if (value < HoldemStatisticsBase.MinPrecision)
                    PersistConfig[ConfigKey.HoldemOptionsViewPrecision] = (int)HoldemStatisticsBase.MinPrecision;
                else
                    PersistConfig[ConfigKey.HoldemOptionsViewPrecision] = value;

                base.RaisePropertyChanged("Precision");
            }
        }

        #endregion //Public Properties

        #region Protected Properties

		protected ICardThemeManager ThemeManager { get { return _themeManager; } }

        public string AdUnitId { get { return _adProvider.AdUnitId; }}

	    public string ApplicationId { get { return _adProvider.ApplicationId; } }

        #endregion //Protected Properties

        #region Constructor

        protected HoldemViewModelBase(
			ICardThemeManager themeManager, 
			IConfigurationService configService,
            IAdProvider adProvider)
			: base(configService)
        {
			if (themeManager == null)
				throw new ArgumentNullException("themeManager");
            if( adProvider == null )
                throw new ArgumentNullException("adProvider");

			_themeManager = themeManager;
		    _adProvider = adProvider;

            this.LoadSavedConfiguration();
        }

        #endregion //Constructor

        #region INotifyPropertyChanged Implementation

        protected virtual BitmapImage GetCardImage(HoldemCard card)
        {
            if (this.Current == null)
				return _themeManager.DefaultCardBack;

        	var cardFromHand = this.Current.FindCard(card);

			return _themeManager.GetCardImage(cardFromHand);
        }

        protected virtual BitmapImage GetCardImageBasedOnState(HoldemCard expected, HoldemCard card)
        {
            if (this.CurrentState >= expected || PersistConfig.Cast<bool>(ConfigKey.HoldemOptionsViewPreview))
                return this.GetCardImage(card);
			return _themeManager.DefaultCardBack;
        }

        protected void UpdateCardImages()
        {
            base.RaisePropertyChanged("HoldemHandCards");
            base.RaisePropertyChanged("HoldemHoleCards");
        }

        #endregion //INotifyPropertyChanged Implementation

        #region Protected Methods

        protected void RunMethodAsync(Action method)
        {
            Scheduler.Dispatcher.Schedule(method);
        }

        private void LoadSavedConfiguration()
        {
            CurrentIndex = 0;
            CurrentState = HoldemCard.Flop2;

            LoadConfiguration();
        }

        private void LoadConfiguration()
        {
            this.NumberOfPlayers = PersistConfig.Cast<int>(ConfigKey.HoldemOptionsViewNumberOfPlayers);

            if( this.NumberOfPlayers < HoldemStatisticsBase.MinPlayers )
                this.NumberOfPlayers = HoldemStatisticsBase.MinPlayers;

            this.Precision = PersistConfig.Get<int>(ConfigKey.HoldemOptionsViewPrecision);
        }

        #endregion
    }
}